package com.tinckay.common.shiro;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tinckay.common.constant.ProjectConstant;
import com.tinckay.common.util.ShiroUtils;
import com.tinckay.entity.po.Menu;
import com.tinckay.entity.po.Role;
import com.tinckay.entity.po.User;
import com.tinckay.service.MenuService;
import com.tinckay.service.RoleService;
import com.tinckay.service.UserService;
import cn.hutool.core.util.StrUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: Jean
 * @Desc:
 * @Date: 2018/10/30 17:32
 */
public class ShiroRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private MenuService menuService;

    /**
     * 授权
     *
     * @param principal
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        User user = ShiroUtils.getCurrentUser();
        String userName = user.getUsername();

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        List<Role> roleList = this.roleService.findUserRole(userName);
        simpleAuthorizationInfo.setRoles(roleList
                .stream()
                .map(Role::getRoleName)
                .collect(Collectors.toSet()));

        List<Menu> permissionList = this.menuService.findUserPermissions(userName);

        simpleAuthorizationInfo.setStringPermissions(permissionList
                .stream()
                .map(Menu::getPerms)
                .filter(perms -> StrUtil.isNotBlank(perms))
                .collect(Collectors.toSet()));
        return simpleAuthorizationInfo;
    }

    /**
     * 认证
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        String username = (String) token.getPrincipal();
        String password = new String((char[]) token.getCredentials());
        User user = this.userService.getOne(new QueryWrapper<User>().lambda().eq(User::getUsername, username));

        if (user == null) {
            throw new UnknownAccountException("用户名或密码错误！");
        }
        if (!password.equals(user.getPassword())) {
            throw new IncorrectCredentialsException("用户名或密码错误！");
        }
        if (!ProjectConstant.VALID_ACCOUNT.equals(user.getStatus())) {
            throw new LockedAccountException("账号已被锁定,请联系管理员！");
        }
        userService.updateLoginTime(user.getId());
        return new SimpleAuthenticationInfo(user, password, getName());
    }
}
